	PAGE	,132								;AN000;
	TITLE	DOS - GRAPHICS Command  -	Profile Load Modules		;AN000;
										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;; DOS - GRAPHICS Command
;; (C) Copyright 1988 Microsoft
;;										;AN000;
;; File Name:  GRLOAD.ASM							;AN000;
;; ----------									;AN000;
;;										;AN000;
;; Description: 								;AN000;
;; ------------ 								;AN000;
;;   This file contains the modules used to load the				;AN000;
;;   GRAPHICS profile into resident memory.					;AN000;
;;										;AN000;
;;   ************* The EGA Dynamic Save Area will be built (by			;AN000;
;;   **  NOTE	** CHAIN_INTERRUPTS in file GRINST.ASM) over top of these	;AN000;
;;   ************* modules to avoid having to relocate this save just before	;AN000;
;;   terminating.  This is safe since the maximum memory used is		;AN000;
;;   288 bytes and the profile loading modules are MUCH larger than		;AN000;
;;   this.  So GRLOAD.ASM MUST be linked before GRINST.ASM and after		;AN000;
;;   GRPRINT.ASM.								;AN000;
;;										;AN000;
;;										;AN000;
;; Documentation Reference:							;AN000;
;; ------------------------							;AN000;
;;	 PLACID Functional Specifications					;AN000;
;;	 OASIS High Level Design						;AN000;
;;	 OASIS GRAPHICS I1 Overview						;AN000;
;;										;AN000;
;; Procedures Contained in This File:						;AN000;
;; ----------------------------------						;AN000;
;;	 LOAD_PROFILE - Main module for profile loading 			;AN000;
;;										;AN000;
;; Include Files Required:							;AN000;
;; -----------------------							;AN000;
;;	 ?????????? - Externals for profile loading modules			;AN000;
;;										;AN000;
;; External Procedure References:						;AN000;
;; ------------------------------						;AN000;
;;	 None									;AN000;
;;										;AN000;
;; Linkage Instructions:							;AN000;
;; ---------------------							;AN000;
;;	 Refer to GRAPHICS.ASM							;AN000;
;;										;AN000;
;; Change History:								;AN000;
;; ---------------								;AN000;
;;										;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
CODE	SEGMENT PUBLIC 'CODE' BYTE     ;;                                       ;AN000;
				       ;;					;AN000;
	INCLUDE STRUC.INC	       ;;					;AN000;
	INCLUDE GRINST.EXT	       ;; Bring in external declarations	;AN000;
				       ;;  for transient command processing	;AN000;
	INCLUDE GRSHAR.STR	       ;;					;AN000;
	INCLUDE GRPARSE.EXT	       ;;					;AN000;
	INCLUDE GRLOAD2.EXT	       ;;					;AN000;
	INCLUDE GRLOAD3.EXT	       ;;					;AN000;
	INCLUDE GRMSG.EQU	       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Public Symbols								;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
   PUBLIC  LOAD_PROFILE 							;AN000;
   PUBLIC  GROW_SHARED_DATA							;AN000;
   PUBLIC  BLOCK_START								;AN000;
   PUBLIC  BLOCK_END								;AN000;
   PUBLIC  FIRST_BLOCK								;AN000;
   PUBLIC  MAX_BLOCK_END							;AN000;
   PUBLIC  GROUPS_DONE								;AN000;
   PUBLIC  STMTS_DONE								;AN000;
   PUBLIC  STMTS_DONE								;AN000;
   PUBLIC  PTD_FOUND								;AN000;
   PUBLIC  BUILD_STATE								;AN000;
   PUBLIC  STMT_ERROR								;AN000;
   PUBLIC  FILE_ERROR								;AN000;
   PUBLIC  PARSE_ERROR								;AN000;
   PUBLIC  END_OF_FILE								;AN000;
   PUBLIC  MEM_OVERFLOW 							;AN000;
   PUBLIC  STMT_BUFFER								;AN000;
   PUBLIC  CUR_STMT								;AN000;
   PUBLIC  PREV_STMT								;AN000;
   PUBLIC  PRT_BOX_ERROR							;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
	ASSUME	CS:CODE,DS:CODE        ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Profile Load Variables							;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
NO	      EQU   0		       ;;					;AN000;
YES	      EQU   1		       ;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   LOAD_PROFILE								;AN000;
;;										;AN000;
;; Input Parameters:								;AN000;
;;   DS,ES,SS - points to our transient segment 				;AN000;
;;										;AN000;
;; Output Parameters:								;AN000;
;;   Temporary Shared Data Area 						;AN000;
;;   Carry flag set if errors in profile.					;AN000;
;;										;AN000;
;; Data Structures Referenced:							;AN000;
;;   Shared Data Area								;AN000;
;;   Profile Load Variables							;AN000;
;;										;AN000;
;; Description: 								;AN000;
;;   Build the profile information in the Temporary Shared Data Area.		;AN000;
;;   The information will be built for the printer type parsed off		;AN000;
;;   the command line.	ALL Printer Type Descriptions will be			;AN000;
;;   parsed to issue error messages and determine the maximum			;AN000;
;;   amount of resident memory required for initial load.			;AN000;
;;   The Shared Data Area begins with a fixed length section			;AN000;
;;   and then has several variable length sections.  PROFILE_BUILD_PTR		;AN000;
;;   is used to build the variable length sections by serving			;AN000;
;;   as a running pointer to the sections as they are built.			;AN000;
;;										;AN000;
;; Register Usage:								;AN000;
;;   BP - points to beginning of Temp Shared Data				;AN000;
;;										;AN000;
;; Called By:									;AN000;
;;   GRAPHICS_INSTALL								;AN000;
;;										;AN000;
;; External Calls:								;AN000;
;;   PARSE_PRINTER, PARSE_DISPLAYMODE, PARSE_SETUP, PARSE_RESTORE		;AN000;
;;   PARSE_PRINTBOX, PARSE_GRAPHICS, PARSE_COLORSELECT, 			;AN000;
;;   PARSE_COLORPRINT, GET_STATEMENT						;AN000;
;;   SYSPARSE									;AN000;
;;										;AN000;
;; Logic:									;AN000;
;;   IF profile path not specified  THEN					;AN000;
;;	PROFILE_PATH := "GRAPHICS.PRO"  /* Current directory */                 ;AN000;
;;	Open profile using PROFILE_PATH 					;AN000;
;;	IF error during open THEN						;AN000;
;;	   PROFILE_PATH := ARG(V0) with "GRAPHICS.COM" replaced                 ;AN000;
;;	     by "GRAPHICS.PRO"                                                  ;AN000;
;;	   Open profile using PROFILE_PATH					;AN000;
;;	   IF error during open THEN						;AN000;
;;	      Issue "Cannot find profile" msg                                   ;AN000;
;;	      Set carry flag							;AN000;
;;	      RETURN								;AN000;
;;	   ENDIF								;AN000;
;;	ENDIF									;AN000;
;;   ELSE									;AN000;
;;	Open profile using specified path					;AN000;
;;	IF error during open THEN						;AN000;
;;	   Issue "Cannot find profile" msg                                      ;AN000;
;;	   Set carry flag							;AN000;
;;	   RETURN								;AN000;
;;	ENDIF									;AN000;
;;   ENDIF									;AN000;
;;   /* don't start building until we find our printer type*/                   ;AN000;
;;   PARSE_MODE := NOBUILD							;AN000;
;;   MAX_BUILD_PTR := 0 							;AN000;
;;   CALL GROW_SHARED_DATA(PROFILE-BUILD_PTR,size of FIXED PART 		;AN000;
;;     of Shared Data Area)							;AN000;
;;   WHILE (not end of file) AND (no I/O error) DO				;AN000;
;;	CALL GET_STATEMENT							;AN000;
;;	IF I/O error THEN							;AN000;
;;	   Issue error message							;AN000;
;;	ELSE									;AN000;
;;	   CALL SYSPARSE to parse the statement verb				;AN000;
;;	   IF verb found THEN							;AN000;
;;	      IF invalid verb THEN						;AN000;
;;		 Issue error message						;AN000;
;;		 PARSE_MODE := ERROR						;AN000;
;;	      ELSE								;AN000;
;;		 CASE statement verb						;AN000;
;;		    PRINTER:							;AN000;
;;		       CALL PARSE_PRINTER					;AN000;
;;		    DISPLAYMODE:						;AN000;
;;		       CALL PARSE_DISPLAYMODE					;AN000;
;;		    PRINTBOX:							;AN000;
;;		       CALL PARSE_PRINTBOX					;AN000;
;;		    SETUP:							;AN000;
;;		       CALL PARSE_SETUP 					;AN000;
;;		    RESTORE:							;AN000;
;;		       CALL PARSE_RESTORE					;AN000;
;;		    GRAPHICS:							;AN000;
;;		       CALL PARSE_GRAPHICS					;AN000;
;;		    COLORPRINT: 						;AN000;
;;		       CALL PARSE_COLORPRINT					;AN000;
;;		    COLORSELECT:						;AN000;
;;		       CALL PARSE_COLORSELECT					;AN000;
;;		 ENDCASE							;AN000;
;;		 IF error on statement THEN					;AN000;
;;		    IF OVERFLOW bit set in RETURN_CODE THEN			;AN000;
;;		       Issue "Insufficient memory" message                      ;AN000;
;;		       RETURN to caller 					;AN000;
;;		    ELSE							;AN000;
;;		       IF MISSING bit set in RETURN_CODE THEN			;AN000;
;;			  Issue "required statement missing" message            ;AN000;
;;		       ENDIF							;AN000;
;;		       IF INVALID bit set in RETURN_CODE THEN			;AN000;
;;			  Issue "statement invalid" message                     ;AN000;
;;		       ENDIF							;AN000;
;;		       IF SEQUENCE bit set in RETURN_CODE THEN			;AN000;
;;			  Issue "out of sequence" message                       ;AN000;
;;		       ENDIF							;AN000;
;;		       display the statement in error				;AN000;
;;		    ENDIF							;AN000;
;;		    PARSE_MODE := ERROR 					;AN000;
;;		 ENDIF								;AN000;
;;	      ENDIF								;AN000;
;;	   ENDIF								;AN000;
;;	ENDIF									;AN000;
;;   ENDWHILE									;AN000;
;;										;AN000;
;;   /* Check length of last PTD */						;AN000;
;;   IF PROFILE_BUILD_PTR > MAX_BUILD_PTR THEN					;AN000;
;;	MAX_BUILD_PTR := PROFILE_BUILD_PTR					;AN000;
;;   ENDIF									;AN000;
;;										;AN000;
;;   /* Make sure all required statements were in previous */			;AN000;
;;   /* Printer Type Description */						;AN000;
;;   /* Must have completed PRINTER, DISPLAYMODE, PRINTBOX and */		;AN000;
;;   /* GRAPHICS statements */							;AN000;
;;   IF PRT+DISP+BOX+GR bits not all set in STMTS_DONE THEN			;AN000;
;;	Issue "required statement missing" message                              ;AN000;
;;	Display "END OF FILE."                                                  ;AN000;
;;   ENDIF									;AN000;
;;										;AN000;
;;   IF errors during build THEN						;AN000;
;;	set carry flag								;AN000;
;;   ELSE									;AN000;
;;	SD_TOTAL_SIZE := MAX_BUILD_PTR - TEMP_SHARED_DATA_PTR			;AN000;
;;   ENDIF									;AN000;
;;   RETURN									;AN000;
;;										;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
FILE_NOT_FOUND	EQU  2		       ;; DOS Int21H error codes		;AN000;
PATH_NOT_FOUND	EQU  3		       ;;					;AN000;
				       ;;					;AN000;
SUBLIST     LABEL  BYTE 	       ;; Message substituion list for stmt #	;AN000;
	    DB	11		       ;; sublist size				;AN000;
	    DB	0		       ;;					;AN000;
	    DW	STMT_NUM	       ;; \ Dword pointer to item		;AN000;
SUBLIST_SEG DW	?		       ;; /					;AN000;
	    DB	1		       ;; Substitution #			;AN000;
;; Flag format	a0sstttt	       ;;					;AN000;
	    DB	00100001B	       ;; Unsigned binary word - left align	;AN000;
;;;;	    DB	00000000B	       ;; charcater				;AN000;
	    DB	0		       ;; max field width			;AN000;
	    DB	1		       ;; min width width			;AN000;
	    DB	' '                    ;; pad characeter                        ;AN000;
				       ;;					;AN000;
STMT_NUM    DW	0		       ;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
FILE_ERROR  DB	0		       ;; Error opening or reading PROFILE	;AN000;
PARSE_ERROR DB	0		       ;; Syntax errors in PROFILE		;AN000;
END_OF_FILE	DB  0		       ;; 1 if end of file			;AN000;
MEM_OVERFLOW  DB  0		       ;; 1 if insufficient memory		;AN000;
				       ;;					;AN000;
STMT_ERROR  DB	0		       ;; Error flag for individual stmt errors ;AN000;
MISSING     EQU 1		       ;; Required statement missing		;AN000;
INVALID     EQU 2		       ;; Invalid statement format		;AN000;
SEQUENCE    EQU 4		       ;; Statement out of sequence		;AN000;
				       ;;					;AN000;
DEFAULT_PATH	  DB "GRAPHICS.PRO",0  ;;                                       ;AN000;
BUFFER	    DB	64 DUP("$")            ;;                                       ;AN000;
				       ;;					;AN000;
HANDLE	    DW	0		       ;; Profile handle			;AN000;
				       ;;					;AN000;
BUILD_STATE DB	0		       ;; 1 if we are currently building	;AN000;
				       ;;  data.  0 means syntax checking	;AN000;
				       ;;   only				;AN000;
				       ;;					;AN000;
				       ;; Keep track of whether this PTD	;AN000;
				       ;;  matches the type requested		;AN000;
PTD_FOUND   DB	0		       ;; Values are NO (0), YES (1) and	;AN000;
PROCESSED   EQU 2		       ;;  PROCESSED (2)			;AN000;
				       ;;					;AN000;
VERB	    DB	0		       ;; PTR into VERB_JMP_TAB 		;AN000;
				       ;;					;AN000;
VERB_JMP_TAB  LABEL WORD	       ;;					;AN000;
	DW  OFFSET PARSE_PRINTER       ;;					;AN000;
	DW  OFFSET PARSE_DISPLAYMODE   ;;					;AN000;
	DW  OFFSET PARSE_PRINTBOX      ;;					;AN000;
	DW  OFFSET PARSE_SETUP	       ;;					;AN000;
	DW  OFFSET PARSE_RESTORE       ;;					;AN000;
	DW  OFFSET PARSE_GRAPHICS      ;;					;AN000;
	DW  OFFSET PARSE_COLORPRINT    ;;					;AN000;
	DW  OFFSET PARSE_COLORSELECT   ;;					;AN000;
	DW  OFFSET PARSE_DARKADJUST    ;;					;AN000;
				       ;;					;AN000;
STMTS_DONE   DW  0		       ;;					;AN000;
GROUPS_DONE  DW  0		       ;;					;AN000;
PREV_STMT    DW  0		       ;;					;AN000;
CUR_STMT     DW  0		       ;;					;AN000;
				       ;;					;AN000;
PRT	EQU  1			       ;; Bit masks for STMTS_DONE and		;AN000;
DISP	EQU  2			       ;;  GROUPS_DONE.  There is one		;AN000;
BOX	EQU  4			       ;;   bit for each statement except	;AN000;
GR	EQU  8			       ;;    DARKADJUST 			;AN000;
SET	EQU  10H		       ;;					;AN000;
REST	EQU  20H		       ;;					;AN000;
COLS	EQU  40H		       ;;					;AN000;
COLP	EQU  80H		       ;;					;AN000;
DARK	EQU  100H		       ;;					;AN000;
				       ;;					;AN000;
BLOCK_START  DW  ?		       ;; Extents of the variable size block	;AN000;
BLOCK_END    DW  ?		       ;;  currently being built		;AN000;
				       ;; These are relative to the		;AN000;
				       ;;  start of the Shared Data Area	;AN000;
				       ;;   so the area can be relocated	;AN000;
MAX_BLOCK_END	DW  0		       ;; End of largest PTD contained		;AN000;
				       ;;  in profile				;AN000;
FIRST_BLOCK  DW  ?		       ;; Pointer to first variable block	;AN000;
				       ;;  (end of fixed part)			;AN000;
PRT_BOX_ERROR  DB  0		       ;;					;AN000;
				       ;;					;AN000;
LOAD_PROFILE  PROC NEAR 	       ;;					;AN000;
				       ;;					;AN000;
  PUSH	CS			       ;;					;AN000;
  POP	SUBLIST_SEG		       ;; setup segment for message sublist	;AN000;
				       ;;					;AN000;
  CALL OPEN_FILE		       ;;					;AN000;
 .IF <FILE_ERROR EQ YES>	       ;; Check for error during open		;AN000;
     STC			       ;;					;AN000;
     RET			       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
				       ;;					;AN000;
  MOV  BP,TEMP_SHARED_DATA_PTR	       ;; BP points to START of Shared Data	;AN000;
  MOV  AX,SIZE SHARED_DATA_AREA_STR    ;; size of fixed part of Shared Data	;AN000;
  MOV  BLOCK_END,0		       ;; Initialize BLOCK_START,BLOCK_END	;AN000;
  MOV  [BP].DARKADJUST_VALUE,0	       ;; Init some values in the fixed 	;AN000;
  MOV  [BP].NUM_PRT_COLOR,0	       ;;  area 				;AN000;
  MOV  [BP].COLORPRINT_PTR,-1	       ;;					;AN000;
  MOV  [BP].NUM_PRT_BANDS,0	       ;;					;AN000;
  MOV  [BP].COLORSELECT_PTR,-1	       ;;					;AN000;
  MOV  [BP].PRINTER_TYPE,BLACK_WHITE   ;;					;AN000;
  CALL GROW_SHARED_DATA 	       ;;  to the first byte after the		;AN000;
				       ;;   fixed part of Shared Data		;AN000;
     MOV  AX,BLOCK_END		       ;; Variable size data will be built	;AN000;
     MOV  BLOCK_START,AX	       ;;  starting at BLOCK_START		;AN000;
     MOV  FIRST_BLOCK,AX	       ;; Save start of variable data		;AN000;
				       ;;					;AN000;
     MOV  SI,BUFFER_PTR 	       ;; Set up SI for GET_BYTE		;AN000;
     CALL GET_BYTE		       ;; Get first byte from file		;AN000;
     MOV  NEXT_BYTE,AL		       ;;  and store it 			;AN000;
     MOV  BUFFER_PTR,SI 	       ;; Save SI for next GET_BYTE		;AN000;
    .WHILE <END_OF_FILE EQ NO> AND     ;; Keep parsing until end of file or	;AN000;
    .WHILE <FILE_ERROR EQ NO>	       ;;  file error occurs			;AN000;
       MOV STMT_ERROR,0 	       ;; Clear parse error flags		;AN000;
       CALL GET_STATEMENT	       ;; Get next profile statement		;AN000;
       INC  STMT_NUM		       ;;					;AN000;
      .IF NC			       ;; Carry flag set if get unsuccessful	;AN000;
	  CALL PARSE_VERB	       ;; Index into verb jump table returned	;AN000;
				       ;;  in BX				;AN000;
	 .IF <AX EQ 0> THEN	       ;; AX=0 if there is a recognized 	;AN000;
	    MOV  AX,CUR_STMT	       ;;					;AN000;
	    MOV  PREV_STMT,AX	       ;; Save last statement verb		;AN000;
	    CALL VERB_JMP_TAB[BX]      ;;  statement to parse			;AN000;
	 .ELSEIF <AX NE -1> THEN       ;;					;AN000;
	    OR	 STMT_ERROR,INVALID    ;;					;AN000;
	    MOV  PARSE_ERROR,YES       ;;					;AN000;
	    MOV  BUILD_STATE,NO        ;;					;AN000;
	 .ENDIF 		       ;;					;AN000;
	 .IF <STMT_ERROR NE 0>	       ;; An error was detected 		;AN000;
	    CALL SHOW_PARSE_ERROR      ;;					;AN000;
	    MOV PARSE_ERROR,YES        ;;					;AN000;
	    MOV STMT_ERROR,0	       ;;					;AN000;
	 .ENDIF 		       ;;					;AN000;
      .ENDIF			       ;;					;AN000;
    .ENDWHILE			       ;;					;AN000;
				       ;;					;AN000;
 .IF <BIT STMTS_DONE  AND PRT>	       ;; Must have at least one PRINTER	;AN000;
     CALL TERMINATE_DISPLAYMODE        ;; Terminate the last PRINTER and	;AN000;
     CALL TERMINATE_PRINTER	       ;;  DISPLAYMODE sections 		;AN000;
 .ELSE				       ;;					;AN000;
     OR  STMT_ERROR,MISSING	       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
 .IF <STMT_ERROR NE 0>		       ;;					;AN000;
     CALL  SHOW_PARSE_ERROR	       ;; Issue Profile syntax messages 	;AN000;
 .ENDIF 			       ;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
  MOV  AX,3E00H 		       ;; Close the file			;AN000;
  MOV  BX,HANDLE		       ;;					;AN000;
  INT  21H			       ;;					;AN000;
				       ;;					;AN000;
 .IF <PARSE_ERROR EQ YES>	       ;;					;AN000;
      MOV  AX,SYNTAX_ERRORS	       ;; Issue "Syntax errors found in         ;AN000;
      MOV  CX,0 		       ;;  profile" message.                    ;AN000;
      CALL DISP_ERROR		       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
				       ;;					;AN000;
 .IF <PTD_FOUND EQ NO>		       ;; Did we find the requested printer	;AN000;
      MOV  AX,INVALID_PRT	       ;;  type?  If not issue error		;AN000;
      MOV  CX,0 		       ;;  message.				;AN000;
      CALL DISP_ERROR		       ;;					;AN000;
      MOV  PARSE_ERROR,YES	       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
				       ;;					;AN000;
 .IF <PARSE_ERROR EQ YES> OR	       ;;					;AN000;
 .IF <PRT_BOX_ERROR EQ YES> OR	       ;;					;AN000;
 .IF <FILE_ERROR EQ YES>	       ;; Set carry flag if profile load	;AN000;
     STC			       ;;  was unsuccessful			;AN000;
 .ELSE				       ;;					;AN000;
    .IF <MEM_OVERFLOW EQ YES>	       ;; Everthing else was OK BUT we ran	;AN000;
	.IF <INSTALLED EQ YES>	       ;;  out of memory!!!			;AN000;
	    MOV   AX,NB_FREE_BYTES     ;;					;AN000;
	   .IF <AX LT RESIDENT_SHARED_DATA_SIZE>				;AN000;
	       MOV   AX,NO_MEMORY      ;; We ran out of physical memory!	;AN000;
	   .ELSE		       ;;					;AN000;
	       MOV   AX,UNABLE_RELOAD  ;; Allocated shared data is too small	;AN000;
	   .ENDIF		       ;;					;AN000;
	.ELSE			       ;;					;AN000;
	    MOV   AX,NO_MEMORY	       ;; We ran out of physical memory 	;AN000;
	.ENDIF			       ;;					;AN000;
	 MOV   CX,0		       ;;					;AN000;
	 CALL  DISP_ERROR	       ;;					;AN000;
	 STC			       ;; Indicate unsuccessful 		;AN000;
    .ELSE			       ;;					;AN000;
	 MOV  AX,MAX_BLOCK_END	       ;; Extent of largest PRINTER section	;AN000;
	 MOV  [BP].SD_TOTAL_SIZE,AX    ;;  we parsed.				;AN000;
	 CLC			       ;; SUCCESSFUL LOAD!!!!			;AN000;
    .ENDIF			       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
				       ;;					;AN000;
  RET				       ;;					;AN000;
				       ;;					;AN000;
LOAD_PROFILE  ENDP		       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   SHOW_PARSE_ERROR								;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
CARRAIGE_RET   EQU  13		       ;;					;AN000;
LINE_FEED      EQU  10		       ;;					;AN000;
				       ;;					;AN000;
SHOW_PARSE_ERROR   PROC 	       ;;					;AN000;
				       ;;					;AN000;
  MOV  ERROR_DEVICE,STDOUT	       ;; profile syntax messages to STDOUT	;AN000;
				       ;;					;AN000;
 .IF <BIT STMT_ERROR AND MISSING>						;AN000;
    PUSH SI		    ;;							;AN000;
    MOV  AX,MISSING_STMT    ;;							;AN000;
    MOV  CX,1		    ;;							;AN000;
    MOV  SI,OFFSET SUBLIST  ;;							;AN000;
    CALL DISP_ERROR	    ;;							;AN000;
    POP  SI		    ;;							;AN000;
 .ENDIF 		    ;;							;AN000;
 .IF <BIT STMT_ERROR AND INVALID>						;AN000;
    PUSH SI		    ;;							;AN000;
    MOV  AX,INVALID_STMT    ;;							;AN000;
    MOV  CX,1									;AN000;
    MOV  SI,OFFSET SUBLIST  ;;							;AN000;
    CALL DISP_ERROR	    ;;							;AN000;
    POP  SI		    ;;							;AN000;
 .ENDIF 		    ;;							;AN000;
 .IF <BIT STMT_ERROR AND SEQUENCE>						;AN000;
    PUSH SI		    ;;							;AN000;
    MOV  AX,OUT_SEQ_STMT    ;;							;AN000;
    MOV  CX,1									;AN000;
    MOV  SI,OFFSET SUBLIST  ;;							;AN000;
    CALL DISP_ERROR	    ;;							;AN000;
    POP  SI		    ;;							;AN000;
 .ENDIF 		    ;;							;AN000;
				       ;;					;AN000;
  MOV  DI,STMT_END_INDEX  ;;							;AN000;
  MOV  STMT_BUFFER[DI],'$'           ;; For display                             ;AN000;
  MOV  AH,9			     ;; 					;AN000;
  MOV  DX,OFFSET STMT_BUFFER							;AN000;
  INT  21H			     ;; 					;AN000;
  MOV  DL,CARRIAGE_RET		     ;; 					;AN000;
  MOV  AH,2			     ;; 					;AN000;
  INT  21H			     ;; 					;AN000;
  MOV  DL,LINE_FEED		     ;; 					;AN000;
  MOV  AH,2			     ;; 					;AN000;
  INT  21H			     ;; 					;AN000;
				       ;;					;AN000;
  MOV  ERROR_DEVICE,STDERR	       ;; reset to STDERR			;AN000;
				       ;;					;AN000;
  RET				       ;;					;AN000;
				       ;;					;AN000;
SHOW_PARSE_ERROR   ENDP 	       ;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   OPEN_FILE									;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
OPEN_FILE     PROC NEAR 	       ;;					;AN000;
				       ;;					;AN000;
 .IF <PROFILE_PATH NE 0>	       ;; If a path was specified then		;AN000;
     MOV  DX,OFFSET PROFILE_PATH       ;;  try and open it			;AN000;
     MOV  AX,3D00H		       ;;					;AN000;
     INT  21H			       ;; Open it				;AN000;
    .IF C			       ;; Open error if carry flag set		;AN000;
       .IF <AX EQ FILE_NOT_FOUND> OR   ;; Check for error other than		;AN000;
       .IF <AX EQ PATH_NOT_FOUND>      ;;  file not found			;AN000;
	   MOV	 AX,PROFILE_NOT_FOUND  ;;					;AN000;
	   MOV	 CX,0		       ;;					;AN000;
	   CALL  DISP_ERROR	       ;; Issue "File not found" common msg     ;AN000;
	   MOV	 FILE_ERROR,YES        ;;					;AN000;
       .ELSE			       ;;					;AN000;
	   CALL  FILE_ERROR_PROC       ;; Issue "Open error"                    ;AN000;
       .ENDIF			       ;;					;AN000;
    .ELSE			       ;;					;AN000;
	MOV  HANDLE,AX		       ;;					;AN000;
    .ENDIF			       ;; File opened OK			;AN000;
 .ELSE				       ;; No path parameter			;AN000;
     MOV  DX,OFFSET DEFAULT_PATH       ;; Try and open "GRAPHICS.PRO"           ;AN000;
     MOV  AX,3D00H		       ;;					;AN000;
     INT  21H			       ;; Open it				;AN000;
    .IF C			       ;; Open error if carry flag set		;AN000;
       .IF <AX EQ FILE_NOT_FOUND> OR   ;; Check for file not found error	;AN000;
       .IF <AX EQ PATH_NOT_FOUND>      ;;					;AN000;
	   CALL COPY_ARGV0	       ;;					;AN000;
	   MOV	DX,OFFSET PROFILE_PATH ;; Try and open "GRAPHICS.PRO" in        ;AN000;
	   MOV	AX,3D00H	       ;;  ARGV0 directory			;AN000;
	   INT	21H		       ;;					;AN000;
	  .IF C 		       ;; Issue "File not found" common msg     ;AN000;
	     .IF <AX EQ FILE_NOT_FOUND> OR					;AN000;
	     .IF <AX EQ PATH_NOT_FOUND> 					;AN000;
		 MOV   AX,PROFILE_NOT_FOUND  ;; 				;AN000;
		 MOV   CX,0		     ;; 				;AN000;
		 CALL  DISP_ERROR	     ;; Issue "File not found"common MSG;AN000;
		 MOV   FILE_ERROR,YES	     ;; 				;AN000;
	     .ELSE		       ;;					;AN000;
		 CALL  FILE_ERROR_PROC ;; Issue "Open error"                    ;AN000;
	     .ENDIF		       ;;					;AN000;
	  .ELSE 		       ;;					;AN000;
	      MOV  HANDLE,AX	       ;;					;AN000;
	  .ENDIF		       ;; File opened OK			;AN000;
       .ELSE			       ;;					;AN000;
	   CALL  FILE_ERROR_PROC       ;; Issue "Open error"                    ;AN000;
       .ENDIF			       ;;					;AN000;
    .ELSE			       ;;					;AN000;
	MOV  HANDLE,AX		       ;;					;AN000;
    .ENDIF			       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
				       ;;					;AN000;
  RET				       ;;					;AN000;
OPEN_FILE     ENDP		       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   COPY_ARGV0 								;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
COPY_ARGV0  PROC		       ;;					;AN000;
				       ;;					;AN000;
  PUSH	 ES			       ;;					;AN000;
  PUSH	 DI			       ;;					;AN000;
  PUSH	 SI			       ;;					;AN000;
				       ;;					;AN000;
  MOV	 DI,2CH 		       ;; Locate environment string		;AN000;
  MOV	 ES,[DI]		       ;;					;AN000;
  XOR	 SI,SI			       ;;					;AN000;
  .WHILE <<WORD PTR ES:[SI]> NE 0>     ;;					;AN000;
     INC   SI			       ;;					;AN000;
  .ENDWHILE			       ;;					;AN000;
  ADD	 SI,4			       ;;					;AN000;
  LEA	 DI,PROFILE_PATH	       ;; Move string to work area		;AN000;
  .REPEAT			       ;;					;AN000;
     MOV    AL,ES:[SI]		       ;;					;AN000;
     MOV    [DI],AL		       ;;					;AN000;
     INC    SI			       ;;					;AN000;
     INC    DI			       ;;					;AN000;
  .UNTIL <<BYTE PTR ES:[SI]> EQ 0>     ;;					;AN000;
  MOV	 BYTE PTR [DI],0	       ;;					;AN000;
  MOV	 BYTE PTR [DI]-3,"P"           ;; Change COM to PRO                     ;AN000;
  MOV	 BYTE PTR [DI]-2,"R"           ;;                                       ;AN000;
  MOV	 BYTE PTR [DI]-1,"O"           ;;                                       ;AN000;
				       ;;					;AN000;
  POP	    SI			       ;;					;AN000;
  POP	    DI			       ;;					;AN000;
  POP	    ES			       ;;					;AN000;
  RET				       ;;					;AN000;
				       ;;					;AN000;
COPY_ARGV0  ENDP		       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   FILE_ERROR_PROC								;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
FILE_ERROR_PROC  PROC		       ;;					;AN000;
  MOV	AX,FILE_ERRORS		       ;;					;AN000;
  MOV	CX,0			       ;;					;AN000;
  CALL	DISP_ERROR		       ;;					;AN000;
  MOV	FILE_ERROR,YES		       ;;					;AN000;
  RET				       ;;					;AN000;
FILE_ERROR_PROC  ENDP		       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   GET_STATEMENT								;AN000;
;;										;AN000;
;; Input Parameters:								;AN000;
;;   NONE									;AN000;
;;										;AN000;
;; Output Parameters:								;AN000;
;;   PROFILE_LINE								;AN000;
;;   RETURN CODE : 0 - successfull read 					;AN000;
;;		 : 1 - end of file						;AN000;
;;		 : 2 - error during read					;AN000;
;;										;AN000;
;;										;AN000;
;; Data Structures Referenced:							;AN000;
;;										;AN000;
;; Description: 								;AN000;
;;   Get a statement from the profile.						;AN000;
;;   The file read in 512 byte buffers and parsed into				;AN000;
;;   lines by the presence of a carriage return at the end of each line.	;AN000;
;;										;AN000;
;; Called By:									;AN000;
;;   LOAD_PROFILE								;AN000;
;;										;AN000;
;; External Calls:								;AN000;
;;   NONE									;AN000;
;;										;AN000;
;; Logic:									;AN000;
;;   FOUND := FALSE								;AN000;
;;   RETURN_CODE := 0								;AN000;
;;   WHILE NOT FOUND DO 							;AN000;
;;	IF end of buffer THEN							;AN000;
;;	   Read next profile record into buffer 				;AN000;
;;	   IF successful read THEN						;AN000;
;;	      point to first byte in buffer					;AN000;
;;	   ELSE 								;AN000;
;;	      IF end of file THEN						;AN000;
;;		 Close profile							;AN000;
;;		 RETURN_CODE := 1						;AN000;
;;		 FOUND := TRUE							;AN000;
;;	      ELSE								;AN000;
;;		 RETURN_CODE := 2						;AN000;
;;		 FOUND := TRUE							;AN000;
;;	      ENDIF								;AN000;
;;	   ENDIF								;AN000;
;;	ENDIF									;AN000;
;;	copy byte to PROFILE_LINE						;AN000;
;;	IF byte in buffer is a CR THEN						;AN000;
;;	   FOUND := TRUE							;AN000;
;;	ENDIF									;AN000;
;;   ENDWHILE									;AN000;
;;   RETURN									;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
FOUND  DB   0			       ;;					;AN000;
				       ;;					;AN000;
CARRIAGE_RET	EQU 13		       ;;					;AN000;
LINE_FEED	EQU 10		       ;;					;AN000;
NEXT_BYTE	DB  0		       ;; Save area for byte just read		;AN000;
BUFFER_SIZE	EQU 512 	       ;;					;AN000;
FILE_BUFFER	DB  512 DUP(0)	       ;;					;AN000;
BUFFER_PTR	DW  512 	       ;;					;AN000;
BUFFER_END	DW  512 	       ;;					;AN000;
STMT_BUFFER	DB  255 DUP(0)	       ;;					;AN000;
		DB  ?		       ;; In case we have to insert a CR	;AN000;
		DB  ?		       ;;  and a LF				;AN000;
		DB  ?		       ;; Too put the "$" for displaying the    ;AN000;
				       ;;  line.				;AN000;
				       ;;					;AN000;
STMT_END_INDEX	DW  ?		       ;;					;AN000;
MAX_STMT_LEN	EQU 255 	       ;;					;AN000;
CR_FOUND	DB  0		       ;; 1 if we found a line terminator	;AN000;
				       ;;					;AN000;
GET_STATEMENT PROC		       ;;					;AN000;
				       ;;					;AN000;
  MOV  FOUND,NO 		       ;;					;AN000;
  MOV  STMT_ERROR,0		       ;; Clear error flags			;AN000;
  XOR  DI,DI			       ;; Index for extracted statement 	;AN000;
  MOV  SI,BUFFER_PTR		       ;; Init file buffer ptr			;AN000;
				       ;;					;AN000;
  MOV  AL,NEXT_BYTE		       ;; Restore current byte			;AN000;
  MOV  CR_FOUND,NO		       ;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
 .WHILE <FOUND EQ NO> AND	       ;; Keep parsing until we find a stmt	;AN000;
 .WHILE <FILE_ERROR EQ NO> AND	       ;;  or a file error occurs		;AN000;
 .WHILE <END_OF_FILE EQ NO>	       ;;   or we reach end of file		;AN000;
   .IF <CR_FOUND EQ YES>	       ;;					;AN000;
      .IF <AL EQ LINE_FEED>	       ;; Return the line feed as well		;AN000;
	 .IF <DI NA MAX_STMT_LEN>      ;; Truncate lines longer than MAX	;AN000;
	     MOV  STMT_BUFFER[DI],AL   ;;  MOVE TO statement buffer		;AN000;
	     INC  DI		       ;; Point to next byte in file buffr	;AN000;
	  .ELSE 		       ;;					;AN000;
	      OR   STMT_ERROR,INVALID  ;; Line has been truncated > ERROR	;AN000;
	      MOV  PARSE_ERROR,YES     ;;					;AN000;
	      MOV  BUILD_STATE,NO      ;;					;AN000;
	 .ENDIF 		       ;;					;AN000;
	  CALL GET_BYTE 	       ;; Get the first byte of next statement	;AN000;
      .ENDIF			       ;;					;AN000;
       MOV  FOUND,YES		       ;; Time to leave this WHILE		;AN000;
       MOV  NEXT_BYTE,AL	       ;; Save the byte we just read		;AN000;
   .ELSE			       ;;					;AN000;
      .IF <DI NA MAX_STMT_LEN>	       ;; Truncate lines longer than MAX	;AN000;
	  MOV  STMT_BUFFER[DI],AL      ;; move byte to statement buffer 	;AN000;
	  INC  DI		       ;; Point to next byte in file buffer	;AN000;
      .ELSE			       ;;					;AN000;
	  OR   STMT_ERROR,INVALID      ;; Line has been truncated > ERROR	;AN000;
	  MOV  PARSE_ERROR,YES	       ;;					;AN000;
	  MOV  BUILD_STATE,NO	       ;;					;AN000;
      .ENDIF			       ;;					;AN000;
      .IF <AL EQ CARRIAGE_RET>	       ;; Found a line terminator		;AN000;
	  MOV  CR_FOUND,YES	       ;; Indicate carriage return found	;AN000;
      .ENDIF			       ;;  and go through once more to		;AN000;
       CALL GET_BYTE		       ;;   check for a line feed		;AN000;
   .ENDIF			       ;;					;AN000;
 .ENDWHILE			       ;;					;AN000;
				       ;;					;AN000;
 .IF <STMT_BUFFER[DI-1] NE CARRIAGE_RET> AND		 ;;			;AN000;
 .IF <STMT_BUFFER[DI-1] NE LINE_FEED>		      ;;			;AN000;
     MOV  STMT_BUFFER[DI],CARRIAGE_RET ;;					;AN000;
     MOV  STMT_BUFFER[DI+1],LINE_FEED  ;;					;AN000;
     INC  DI			       ;;					;AN000;
     INC  DI			       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
  MOV STMT_END_INDEX,DI 	       ;;					;AN000;
  MOV BUFFER_PTR,SI		       ;; Save buffer ptr for next time 	;AN000;
				       ;;					;AN000;
 .IF <END_OF_FILE EQ YES>	       ;;					;AN000;
     .IF <DI EQ 0>		       ;; Clear carry if we read something	;AN000;
	STC			       ;;  and no file error occured otherwise	;AN000;
     .ELSE			       ;;   set carry indicating unsuccessful	;AN000;
	CLC			       ;;    get.				;AN000;
     .ENDIF			       ;;					;AN000;
 .ELSE				       ;;					;AN000;
     .IF <FILE_ERROR EQ YES>	       ;;					;AN000;
	 STC			       ;;					;AN000;
     .ELSE			       ;;					;AN000;
	 CLC			       ;;					;AN000;
     .ENDIF			       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
  RET				       ;;					;AN000;
				       ;;					;AN000;
GET_STATEMENT ENDP		       ;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   GET_BYTE									;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
GET_BYTE      PROC		       ;;					;AN000;
				       ;;					;AN000;
 .IF <SI EQ BUFFER_END> 	       ;; If buffer empty do another read	;AN000;
     MOV  AH,3FH		       ;;					;AN000;
     MOV  DX,OFFSET FILE_BUFFER        ;;					;AN000;
     MOV  CX,BUFFER_SIZE	       ;;					;AN000;
     MOV  BX,HANDLE		       ;;					;AN000;
     INT  21H			       ;;					;AN000;
    .IF C			       ;; Carry set by DOS if file error	;AN000;
	CALL FILE_ERROR_PROC	       ;;					;AN000;
    .ELSE			       ;;					;AN000;
       .IF <AX EQ 0>		       ;; End of file if AX=0			;AN000;
	   MOV	END_OF_FILE,YES        ;;					;AN000;
	   MOV	AH,3EH		       ;; Close the file			;AN000;
	   MOV	BX,HANDLE	       ;;					;AN000;
	   INT	21H		       ;;					;AN000;
       .ELSE			       ;;					;AN000;
	   MOV BUFFER_END,AX	       ;; Number of bytes read			;AN000;
	   XOR SI,SI		       ;; Buffer pointer := 0			;AN000;
       .ENDIF			       ;;					;AN000;
    .ENDIF			       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
				       ;;					;AN000;
 .IF <FILE_ERROR EQ YES> OR	       ;;					;AN000;
 .IF <END_OF_FILE EQ YES>	       ;;					;AN000;
     STC			       ;; Unsuccessful get			;AN000;
 .ELSE				       ;;					;AN000;
    .IF <<FILE_BUFFER[SI]> EQ 1AH>	;; cHECK for EOF marker 		;AN000;
	MOV END_OF_FILE,YES	       ;;					;AN000;
	STC			       ;;					;AN000;
    .ELSE			       ;;					;AN000;
	MOV  AL,FILE_BUFFER[SI] 	  ;; Return byte in AL			;AN000;
	INC  SI 			  ;;					;AN000;
	CLC				  ;; Successful get			;AN000;
    .ENDIF				  ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
  RET				       ;;					;AN000;
				       ;;					;AN000;
GET_BYTE      ENDP		       ;;					;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Module Name: 								;AN000;
;;   GROW_SHARED_DATA								;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
GROW_SHARED_DATA  PROC		       ;;					;AN000;
  PUSH BX			       ;;					;AN000;
  ADD  BLOCK_END,AX		       ;; Grow the current block by AX		;AN000;
  MOV  BX,BLOCK_END		       ;;					;AN000;
 .IF <BX A NB_FREE_BYTES>	       ;; Check for overflow			;AN000;
     MOV  BUILD_STATE,NO	       ;; Stop building shared data		;AN000;
     MOV  MEM_OVERFLOW,YES	       ;;					;AN000;
 .ENDIF 			       ;;					;AN000;
  POP  BX			       ;;					;AN000;
  RET				       ;;					;AN000;
GROW_SHARED_DATA  ENDP		       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
										;AN000;
CODE	ENDS			       ;;					;AN000;
	END									;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
